#include "MainWindow.h"
#include <QScrollArea>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QKeySequence>

MainWindow::MainWindow(QWidget* parent): QMainWindow(parent)
{
    setupUi(this);

    /*

      goal:

      |-------------------------------------|
      |    central_widget                   |
      |    |-----------|------------------| |
      |    |           | scroll_area      | |
      |    | _glwidget | |--------------| | |
      |    |           | | _side_window | | |
      |    |           | |              | | |
      |    |           | |--------------| | |
      |    |-----------|------------------| |
      |                                     |
      |-------------------------------------|

    */

    // creating instances of GLWidget and SideWindow
    _glwidget = new GLWidget;
    _side_window = new SideWindow;

    // creating a scroll area
    QScrollArea* scroll_area = new QScrollArea;

    // making _side_window scrollable
    scroll_area->setWidget(_side_window);

    // copying the size policy of _side_window
    scroll_area->setSizePolicy(_side_window->sizePolicy());

    // creating a horizontal box layout
    QHBoxLayout* hbox = new QHBoxLayout;
    hbox->addWidget(_glwidget);
    hbox->addWidget(scroll_area);

    // creating the central widget of the main window
    QWidget* central_widget = new QWidget;
    central_widget->setLayout(hbox);

    // setting the central widget of the main window
    setCentralWidget(central_widget);

    // creating connections by means of the SIGNAL and SLOT mechanism of Qt
    // buttons widgets handled in the glwidget
    connect(_side_window->x_rotate_slider, SIGNAL(valueChanged(int)), _glwidget, SLOT(set_x_angle(int)));
    connect(_side_window->y_rotate_slider, SIGNAL(valueChanged(int)), _glwidget, SLOT(set_y_angle(int)));
    connect(_side_window->z_rotate_slider, SIGNAL(valueChanged(int)), _glwidget, SLOT(set_z_angle(int)));
    connect(_side_window->zoom_spin_box, SIGNAL(valueChanged(double)), _glwidget, SLOT(set_scale_factor(double)));
    connect(_side_window->directional_light_rb, SIGNAL(toggled(bool)), _glwidget, SLOT(enable_directional_light(bool)));
    connect(_side_window->two_sided_lighting_rb, SIGNAL(toggled(bool)), _glwidget, SLOT(enable_two_sided_lighting(bool)));
    connect(_side_window->toon_rb, SIGNAL(toggled(bool)), _glwidget, SLOT(enable_toon_light(bool)));
    connect(_side_window->light_source_0_ckb, SIGNAL(toggled(bool)), _glwidget, SLOT(enable_light_source_0(bool)));
    connect(_side_window->light_source_1_ckb, SIGNAL(toggled(bool)), _glwidget, SLOT(enable_light_source_1(bool)));
    connect(_side_window->light_source_2_ckb, SIGNAL(toggled(bool)), _glwidget, SLOT(enable_light_source_2(bool)));

    // menu handled here
    connect(this->actionGenNewSurf, SIGNAL(triggered()), this, SLOT(GenNewSurf_triggered()));

    // CP manipulation handled here
    connect(_side_window->control_point_manipulation_enable_ckb, SIGNAL(toggled(bool)), this, SLOT(ControlPointManipulation_enable(bool)));
    connect(_side_window->control_point_sb, SIGNAL(valueChanged(int)), this, SLOT(ControlPointIndex_changed(int)));
    connect(_side_window->control_point_sl, SIGNAL(valueChanged(int)), this, SLOT(ControlPointIndex_changed(int)));
    connect(_side_window->control_point_manipulation_btb, SIGNAL(accepted()), this, SLOT(ControlPointManipuilation_accepted()));
    connect(_side_window->control_point_manipulation_btb, SIGNAL(rejected()), this, SLOT(ControlPointManipuilation_rejected()));

    // CP manipulation hadled in the glwidget
    connect(_side_window->control_point_manipulation_btb, SIGNAL(accepted()), _glwidget, SLOT(ControlPointManipulation_accepted()));
    connect(_side_window->control_point_manipulation_btb, SIGNAL(rejected()), _glwidget, SLOT(ControlPointManipulation_rejected()));
    connect(_side_window->x_dsb, SIGNAL(valueChanged(double)), _glwidget, SLOT(ControlPoint_x_changed(double)));
    connect(_side_window->y_dsb, SIGNAL(valueChanged(double)), _glwidget, SLOT(ControlPoint_y_changed(double)));
    connect(_side_window->z_dsb, SIGNAL(valueChanged(double)), _glwidget, SLOT(ControlPoint_z_changed(double)));

    //textura betoltese
    connect(_side_window->load_texture_button,SIGNAL(clicked()),_glwidget,SLOT(LoadTexture_button()));
}

void MainWindow::on_actionE_xit_triggered()
{
    qApp->quit();
}

void MainWindow::GenNewSurf_triggered()
{
    GenerateNewSurface genNewSurf;
    if (genNewSurf.exec() == QDialog::Accepted)
    {
        _glwidget->CreateAndReplaceActualSurfaceObject(
                genNewSurf.surface_type_cb->currentIndex(),
                genNewSurf.nr_rows_sb->value(),
                genNewSurf.nr_columns_sb->value(),
                genNewSurf.u_div_point_count_sb->value(),
                genNewSurf.v_div_point_count_sb->value(),
                genNewSurf.param_0_dsb->value(),
                genNewSurf.param_1_dsb->value(),
                genNewSurf.param_2_dsb->value());
    }
}

void MainWindow::keyPressEvent(QKeyEvent *e)
{
    switch (e->key())
    {
    case Qt::Key_W:
        _glwidget->Walk(-0.5);
        break;
    case Qt::Key_A:
        _glwidget->Strafe(-0.5);
        break;
    case Qt::Key_S:
        _glwidget->Walk(0.5);
        break;
    case Qt::Key_D:
        _glwidget->Strafe(0.5);
        break;
    case Qt::Key_Q:
        _glwidget->Heighten(-0.5);
        break;
    case Qt::Key_E:
        _glwidget->Heighten(0.5);
        break;
    case Qt::Key_I:
        _glwidget->Pitch(-0.5);
        break;
    case Qt::Key_J:
        _glwidget->Yaw(0.5);
        break;
    case Qt::Key_K:
        _glwidget->Pitch(0.5);
        break;
    case Qt::Key_L:
        _glwidget->Yaw(-0.5);
        break;
    case Qt::Key_U:
        _glwidget->Roll(0.5);
        break;
    case Qt::Key_O:
        _glwidget->Roll(-0.5);
        break;
    }
}

void MainWindow::ControlPointManipulation_enable(bool enable)
{
    if (!_glwidget->ControlPointManipulation_enable(enable))
        return;

    if (enable)
    {
        GLuint count;
        GLdouble x, y, z;
        _glwidget->GetControlPointsInformation(count, x, y, z);
        _side_window->control_point_sb->setMaximum(count - 1);
        _side_window->control_point_sl->setMaximum(count - 1);
        _side_window->x_dsb->setValue(x);
        _side_window->y_dsb->setValue(y);
        _side_window->z_dsb->setValue(z);
    }
    else
    {
        _side_window->control_point_sb->setMaximum(0);
        _side_window->control_point_sl->setMaximum(0);
        _side_window->x_dsb->setValue(0.0);
        _side_window->y_dsb->setValue(0.0);
        _side_window->z_dsb->setValue(0.0);
    }
}

void MainWindow::ControlPointIndex_changed(int index)
{
    _glwidget->ControlPointIndex_changed(index);
    if (_side_window->control_point_sb->value() != index)
        _side_window->control_point_sb->setValue(index);
    if (_side_window->control_point_sl->value() != index)
        _side_window->control_point_sl->setValue(index);

    GLuint count;
    GLdouble x, y, z;
    _glwidget->GetControlPointsInformation(count, x, y, z);
    _side_window->x_dsb->setValue(x);
    _side_window->y_dsb->setValue(y);
    _side_window->z_dsb->setValue(z);
}

void MainWindow::ControlPointManipuilation_accepted()
{

}

void MainWindow::ControlPointManipuilation_rejected()
{

}

